package com.xmg.dataStructure.josephus;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Josephus {
    public static void main(String[] args) {
        CircleSingleLinkedList list = new CircleSingleLinkedList();
        list.addBoy(41);
//        list.showBoy();

        list.countBoy(1,3,41);

        LocalDateTime dateTime = LocalDateTime.of(2021, 22, 23, 9, 53);
        System.out.println(dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
    }
}
//创建一个环形的单向链表
class CircleSingleLinkedList{
    //创建一个first节点，当前没有编号
    private Boy first = new Boy(-1);
    //添加小孩节点，构建成一个环形的链表
    public void addBoy(int nums){
        if(nums<1){
            return;
        }
        Boy curBoy = null;
        for (int i = 1; i <= nums ; i++) {
            Boy boy = new Boy(i);
            if(i==1){
                first = boy;
                first.setNext(first);
                curBoy = first;
            }else{
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }
        }
    }

    //遍历当前环形链表
    public void showBoy(){
        if(first==null){
            System.out.println("没有任何小孩");
        }
        //first不能动，仍然需要一个辅助指针完成遍历
        Boy curBoy = first;
        while (true){
            System.out.printf("小孩的编号%d \n",curBoy.getNo());
            if(curBoy.getNext()==first){
                break;
            }
            curBoy = curBoy.getNext();
        }
    }

    public void countBoy(int startNo,int countNum,int nums){
        //校验数据
        if (first == null || startNo < 1 || startNo > nums){
            System.out.println("参数输入错误，请重新输入");
            return;
        }
        //创建一个辅助指针，帮助完成小孩出圈
        Boy helper = first;
        while (true){
            if(helper.getNext()==first){
                break;
            }
            helper = helper.getNext();
        }
        //小孩报数前，先让first和helper移动k-1次
        for (int j=0;j<startNo-1;j++){
            first = first.getNext();
            helper = helper.getNext();
        }
        //当小孩报数时，让first和helper指针同时移动m-1次，然后出圈
        //这里是一个循环操作，直到圈中只有一个节点
        while(true){
            if(helper==first){//说明圈中只有一个节点
                System.out.printf("小孩%d留在圈中\n",first.getNo());
                break;
            }
            for (int j = 0; j < countNum - 1; j++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            System.out.printf("小孩%d出圈\n",first.getNo());
            first = first.getNext();
            helper.setNext(first);
        }
    }
}

class Boy{
    private int no;
    private Boy next;

    public Boy(int no) {
        this.no = no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Boy getNext() {
        return next;
    }

    public void setNext(Boy next) {
        this.next = next;
    }
}
